package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.lfasr.concurrent.ConcurrentLockAspect;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.pro.assemble.pojo.dto.AssembleDeleteBatchDTO;
import com.xbongbong.pro.assemble.pojo.dto.AssembleEditAttrUpdateDTO;
import com.xbongbong.pro.assemble.pojo.dto.AssembleUpdateBatchDTO;
import com.xbongbong.pro.assemble.pojo.dto.AssembleUpdateByBusinessRuleDTO;
import com.xbongbong.pro.assemble.pojo.dto.AssembleUpdateDTO;
import com.xbongbong.pro.assemble.pojo.vo.AssembleDeleteBatchVO;
import com.xbongbong.pro.assembleproduct.pojo.dto.AssembleProductDeleteBatchDTO;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.LinkProductRelyEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.instock.pojo.dto.InstockDeleteBatchDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockListDTO;
import com.xbongbong.pro.instock.pojo.vo.InstockListVO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.outstock.pojo.dto.OutStockListDTO;
import com.xbongbong.pro.outstock.pojo.dto.OutstockDeleteBatchDTO;
import com.xbongbong.pro.outstock.pojo.vo.OutStockListVO;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.productbaseinfo.pojo.dto.ProductBaseInfoDeleteBatchDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.analytical.impl.AssembleValidateAnalyticalServiceImpl;
import com.xbongbong.saas.annotation.BusinessTypeToServiceAnnotation;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.AssembleProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductBaseInfoEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.domain.entity.ext.AssembleEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.BusinessTypeToServiceEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperatePageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.WarehouseEnum;
import com.xbongbong.saas.enums.product.AssembleInProductEnum;
import com.xbongbong.saas.enums.product.AssembleProductEnum;
import com.xbongbong.saas.enums.product.TransferProductEnum;
import com.xbongbong.saas.help.BatchSeqExplainHelp;
import com.xbongbong.saas.help.DefaultAttrHelp;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.workflow.ProductSerialHelp;
import com.xbongbong.saas.model.AssembleModel;
import com.xbongbong.saas.model.AssembleProductModel;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.LinkProductRelyModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductBaseInfoModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.service.AssembleProductService;
import com.xbongbong.saas.service.AssembleService;
import com.xbongbong.saas.service.BusinessProductService;
import com.xbongbong.saas.service.FormatSpecialBusinessService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.OutstockService;
import com.xbongbong.saas.service.ProductBaseInfoService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.*;

/**
 * 装配单service实现层
 *
 * @author Jian.Wang
 * @version v1.0
 * @date 2019-02-21 12:23
 * @since v1.0
 **/
@Service("AssembleService")
@BusinessTypeToServiceAnnotation(businessService = BusinessTypeToServiceEnum.ASSEMBLE)
public class AssembleServiceImpl implements AssembleService, FormatSpecialBusinessService {

    private static final Logger LOG = LoggerFactory.getLogger(AssembleServiceImpl.class);

    @Resource
    private DefaultAttrHelp defaultAttrHelp;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private ProductModel productModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private AssembleProductModel assembleProductModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ProductBaseInfoModel productBaseInfoModel;
    @Resource
    private AssembleModel assembleModel;
    @Resource
    private AssembleProductService assembleProductService;
    @Resource
    private ProductBaseInfoService productBaseInfoService;
    @Resource
    private InstockService instockService;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private OutstockService outstockService;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private ProductHelp productHelp;
    @Resource
    private LinkProductRelyModel linkProductRelyModel;
    @Resource
    private UserHelp userHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private BusinessProductService businessProductService;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private SaasDeleteHelp saasDeleteHelp;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private AssembleValidateAnalyticalServiceImpl assembleAnalyticalService;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private ConcurrentLockAspect concurrentLockAspect;
    @Resource
    private ProductSerialHelp productSerialHelp;

    /**
     * 装配单保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 异常
     * @author Jian.Wang
     * @date 2019-02-21 12:23
     * @since v1.0
     **/
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        assembleAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 产品校验
     * @param outProductArray
     * @param inProductArray
     * @param corpid
     * @param outWarehouseId
     * @throws XbbException
     */
    @Override
    public void validateDataOutProduct(JSONArray outProductArray,JSONArray inProductArray,String corpid,Long outWarehouseId) throws XbbException {
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Object object:outProductArray) {
            JSONObject jsonObject = (JSONObject) object;
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
            Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            Double num = productNumMap.getOrDefault(productId,0D);
            num += productNum;
            productNumMap.put(productId,num);
        }
        for (Object object:inProductArray) {
            JSONObject jsonObject = (JSONObject) object;
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
            Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            Double num = productNumMap.getOrDefault(productId,0D);
            num += productNum;
            productNumMap.put(productId,num);
        }
        formDataValidateProductHelp.productExit(corpid,new ArrayList<>(pageProductIds));
        boolean outStockRule = true;
        FormConfigEntity formConfigEntity = formConfigModel.getEntityByBusinessType(corpid, XbbRefTypeEnum.OUTSTOCK.getCode(), FormConfigEnum.OUTSTOCK_INSUFFICIENT_NOT_ALLOW_WAREHOUSING.getConfig());
        if (Objects.nonNull(formConfigEntity)) {
            if (!Objects.equals(formConfigEntity.getConfigValue(), "1")) {
                outStockRule = false;
            }
        }
        if (outStockRule){
            formDataValidateProductHelp.warehouseProductNumLegalCheck(corpid,outProductArray,outWarehouseId,false, OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode());
        } else {
            // 解析装配出库产品的仓库字段
            for (int i = 0; i < outProductArray.size(); i++) {
                JSONObject productObj = outProductArray.getJSONObject(i);
                saasSaveHelp.formatLinkBusiness4Save(productObj,SelectProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            }
        }
        // 解析装配入库产品的仓库字段
        for (int i = 0; i < inProductArray.size(); i++) {
            JSONObject productObj = inProductArray.getJSONObject(i);
            saasSaveHelp.formatLinkBusiness4Save(productObj,SelectProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
        }
    }

    /**
     * 装配单保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 异常
     * @author Jian.Wang
     * @date 2019-02-21 12:23
     * @since v1.0
     **/
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        if (saasFormSaveDTO.getIsNew()) {
            SaasFormSaveDTO checkDTO = (SaasFormSaveDTO) CloneUtil.deepClone(saasFormSaveDTO);
            String corpid = checkDTO.getCorpid();
            JSONObject newData = checkDTO.getNewData();
            Long inWarehouseId = newData.getLong(AssembleEnum.INTO_WAREHOUSE_ID.getAttr());
            Long outWarehouseId = newData.getLong(AssembleEnum.OUT_WAREHOUSE_ID.getAttr());
            String inProductAttr = AssembleEnum.IN_PRODUCTS.getAttr();
            String outProductAttr = AssembleEnum.OUT_PRODUCTS.getAttr();
            JSONArray inProductArray = saasSaveHelp.formatSelectProduct4Save2(newData, inProductAttr);
            JSONArray outProductArray = saasSaveHelp.formatSelectProduct4Save2(newData, outProductAttr);
            boolean isCheck = concurrentLockAspect.checkStock(corpid);
            // 没开启负库存的才超发出库校验
            if (isCheck){
                // 装配单出库超发控制
                if (CollectionUtils.isNotEmpty(outProductArray)){
                    concurrentLockAspect.checkInventory(outProductArray,outWarehouseId,corpid,true,XbbRefTypeEnum.ASSEMBLE.getCode());
                }
                // 装配入库超发控制
                if (CollectionUtils.isNotEmpty(inProductArray)){
                    concurrentLockAspect.checkInventory(inProductArray,inWarehouseId,corpid,false,XbbRefTypeEnum.ASSEMBLE.getCode());
                }
            }
            Runnable runnable = () -> {
                try {
                    saveProduct(saasFormSaveDTO.getNewData(), saasFormSaveDTO.getCorpid(), saasFormSaveDTO.getNewPaasFormDataEntity().getId());
//                    generateStockSheet(saasFormSaveDTO);
                    saasSaveHelp.generateStockSheet(saasFormSaveDTO);
                } catch (Exception e) {
                    if (isCheck){
                        // 没开启负库存的才回滚
                        concurrentLockAspect.InventorytockAndAssembleRollBack(inProductArray, outProductArray);
                    }
                    LOG.error("AssembleServiceImpl.afterSave 执行出错", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        }
    }

    private void saveProduct(JSONObject data, String corpid, Long dataId) throws XbbException {
        JSONArray outProductArray = data.getJSONArray(AssembleEnum.OUT_PRODUCTS.getAttr());
        JSONArray inProductArray = data.getJSONArray(AssembleEnum.IN_PRODUCTS.getAttr());

        JSONArray productArray = new JSONArray();
        productArray.addAll(outProductArray);
        productArray.addAll(inProductArray);
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        // 保存装配出库产品
        saveProduct(corpid, dataId, 1, outProductArray, productMap);
        // 保存装配入库产品
        saveProduct(corpid, dataId, 2, inProductArray, productMap);
    }

    /**
     * 将保存出库产品和入库产品封装成一个方法，并将批次信息和序列号信息存入对应的数据中
     * @param corpid 公司id
     * @param dataId 装配出入库数据id
     * @param type 出入库类型
     * @param productArray 产品
     * @param productMap 产品汇总
     * @throws XbbException
     */
    private void saveProduct(String corpid, Long dataId, Integer type, JSONArray productArray, Map<Long, PaasFormDataEntityExt> productMap) throws XbbException {
        List<AssembleProductEntity> inProductList = new ArrayList<>();
        int sort = 0;
        Map<Integer, JSONArray> inProductSeqMap = new HashMap<>(productArray.size());
        Map<Integer, ProductBaseInfoEntity> inProductBaseInfoMap = new HashMap<>(productArray.size());
        Map<Integer, AssembleProductEntity> insertProductMap = new HashMap<>(productArray.size());
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            JSONArray seqArray = jsonObject.getJSONArray(ProductConstant.SEQ);
            // 去除序列号数据
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Double productNum = jsonObject.getDouble(AssembleProductEnum.NUM.getAttr());
            sort++;
            JSONObject productData = productMap.get(pageProductId).getData();
            AssembleProductEntity assembleProduct = new AssembleProductEntity();
            assembleProduct.setCorpid(corpid);
            assembleProduct.setAssembleId(dataId);
            assembleProduct.setType(type);
            assembleProduct.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            assembleProduct.setProductId(pageProductId);
            assembleProduct.setProductNum(productNum);
            assembleProduct.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            assembleProduct.setProductNo(productMap.get(pageProductId).getSerialNo());
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, assembleProduct);
                assembleProduct.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                assembleProduct.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(TransferProductEnum.UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            assembleProduct.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            assembleProduct.setCost(jsonObject.getDouble(AssembleProductEnum.COST.getAttr()));
            assembleProduct.setProductPrice(productData.getDouble(ProductEnum.PRICE.getAttr()));
            assembleProduct.setBatch(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()));
            assembleProduct.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
            Long guaranteePeriod = jsonObject.getLong(AssembleProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : jsonObject.getLong(AssembleProductEnum.GUARANTEE_PERIOD.getAttr());
            assembleProduct.setGuaranteePeriod(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
            saasSaveHelp.formatLinkBusiness4Save(jsonObject,AssembleProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            Long warehouseId = jsonObject.getLong(AssembleProductEnum.WAREHOUSE.getAttr());
            assembleProduct.setWarehouseId(warehouseId);
            assembleProduct.setAddTime(DateTimeUtil.getInt());
            assembleProduct.setUpdateTime(DateTimeUtil.getInt());

            assembleProduct.setDel(0);
            assembleProduct.setSort(sort);
            assembleProduct.setData(jsonObject);
            inProductList.add(assembleProduct);
            insertProductMap.put(i, assembleProduct);
//            assembleProductModel.save(assembleProduct);

            // 生成出入库单，会用到这个属性
//            jsonObject.put(BusinessConstant.REF_PRODUCT_ID, assembleProduct.getId());
            if (Objects.nonNull(seqArray) && !seqArray.isEmpty()) {
//                jsonObject.put(ProductConstant.SEQ, seqArray);
                inProductSeqMap.put(i, seqArray);
            }

            if (StringUtil.isNotEmpty(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()))) {
                JSONObject productBaseInfoData = new JSONObject();
                productBaseInfoData.putAll(jsonObject);
                if (Objects.nonNull(assembleProduct.getBusinessUnit())) {
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_UNIT.getAttr(), assembleProduct.getBusinessUnit());
                    productBaseInfoData.put(SelectProductEnum.RATE.getAttr(), assembleProduct.getRate());
                    productBaseInfoData.put(SelectProductEnum.UNIT_GROUP.getAttr(), assembleProduct.getGroupId());
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_NUM.getAttr(), assembleProduct.getBusinessNum());
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_COST.getAttr(),assembleProduct.getPriceData().get(SelectProductEnum.COST.getAttr()));
                }
                ProductBaseInfoEntity productBaseInfoEntity = new ProductBaseInfoEntity();
                productBaseInfoEntity.setCorpid(corpid);
                productBaseInfoEntity.setFormId(0L);
                productBaseInfoEntity.setRefId(assembleProduct.getId());
                productBaseInfoEntity.setRefType(XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
                productBaseInfoEntity.setBatch(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()));
                productBaseInfoEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
                productBaseInfoEntity.setGuaranteePeriod(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                productBaseInfoEntity.setMemo(jsonObject.getString(AssembleProductEnum.MEMO.getAttr()));
                productBaseInfoEntity.setData(productBaseInfoData);
                productBaseInfoEntity.setDel(0);
                productBaseInfoEntity.setAddTime(DateTimeUtil.getInt());
                productBaseInfoEntity.setUpdateTime(DateTimeUtil.getInt());
//                productBaseInfoEntityList.add(productBaseInfoEntity);
                inProductBaseInfoMap.put(i, productBaseInfoEntity);
            }
        }
        assembleProductModel.insertBatch(inProductList);
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long id = jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID);
            if (insertProductMap.containsKey(i)) {
                id = insertProductMap.get(i).getId();
                jsonObject.put(BusinessConstant.REF_PRODUCT_ID, id);
            }
            if (inProductSeqMap.containsKey(i)) {
                jsonObject.put(ProductConstant.SEQ, inProductSeqMap.get(i));
            }
            if (inProductBaseInfoMap.containsKey(i)) {
                ProductBaseInfoEntity productBaseInfoEntity = inProductBaseInfoMap.get(i);
                productBaseInfoEntity.setRefId(id);
                productBaseInfoEntity.getData().put(BusinessConstant.REF_PRODUCT_ID, id);
                inProductBaseInfoMap.put(i, productBaseInfoEntity);
            }
        }
        List<ProductBaseInfoEntity> productBaseInfoList = new ArrayList<>();
        inProductBaseInfoMap.forEach((key, value)->{
            productBaseInfoList.add(value);
        });
        if (!productBaseInfoList.isEmpty()){
            productBaseInfoModel.insertBatch(productBaseInfoList);
        }
    }



    /**
     * 新建时格式化解释
     *
     * @param formatExplainDTO 入参
     * @throws XbbException 异常
     */
    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        String corpid = formatExplainDTO.getCorpid();
        String platForm = formatExplainDTO.getPlatform();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(attr, AssembleEnum.IN_PRODUCTS.getAttr())) {
                fieldAttrEntity.setSupportScanning(BasicConstant.ONE);
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.ASSEMBLE, corpid, OperatePageEnum.NEW.getCode(), false);
                if (Objects.equals(platForm, PlatFormEnum.DINGTALK.getValue())) {
                    SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                    saasParticularAttributePoJo.setProductRelyAttr(AssembleEnum.INTO_WAREHOUSE_ID.getAttr());
                }
            } else if (Objects.equals(attr, AssembleEnum.OUT_PRODUCTS.getAttr())) {
                fieldAttrEntity.setSupportScanning(BasicConstant.ONE);
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.ASSEMBLE, corpid, OperatePageEnum.NEW.getCode(), false);
                if (Objects.equals(platForm, PlatFormEnum.DINGTALK.getValue())) {
                    SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                    saasParticularAttributePoJo.setProductRelyAttr(AssembleEnum.OUT_WAREHOUSE_ID.getAttr());
                }
            }
            // 装配日期设置默认值
            if (Objects.equals(fieldAttrEntity.getAttr(),AssembleEnum.ASSEMBLE_TIME.getAttr())) {
                DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
                defaultAttrPoJo.setDefaultValue(DateUtil.getTodayInt() + "");
                defaultAttrPoJo.setDefaultType("dateByBackEnd");
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), AssembleEnum.MANAGER_ID.getAttr())) {
                if(fieldAttrEntity.getDefaultAttr() == null || (fieldAttrEntity.getDefaultAttr() != null && fieldAttrEntity.getDefaultAttr().getDefaultList() == null)) {
                    fieldAttrEntity.setDefaultAttr(defaultAttrHelp.setUserDefaultAttrPoJo(formatExplainDTO.getUserId(), formatExplainDTO.getLoginUser().getName(),formatExplainDTO.getLoginUser().getAvatar()));
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AssembleDeleteBatchVO deleteBatch(AssembleDeleteBatchDTO assembleDeleteBatchDTO) throws XbbException {
        String corpid = assembleDeleteBatchDTO.getCorpid();
        List<Long> assembleIdList = assembleDeleteBatchDTO.getDataIdList();
        AssembleDeleteBatchVO assembleDeleteBatchVO = new AssembleDeleteBatchVO();
        List<String> no= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, String> instockIdAndno= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {
            // TODO 删除权限校验
            // 删除装配出入库单
            Map<String, Object> param = BeanUtil.convertBean2Map(assembleDeleteBatchDTO, true);
            param.put("ids", assembleIdList);
            List<AssembleEntityExt> assembleList = assembleModel.findEntitys(param);
            if (assembleList.size() != assembleIdList.size()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.ASSEMBLE_NOT_EXISTS);
            }
            //结账内校验
            for (AssembleEntityExt assembleEntityExt : assembleList) {
                JSONObject data = assembleEntityExt.getData();
                Long date = data.getLong(AssembleEnum.ASSEMBLE_TIME.getAttr());
                //结账中校验
                String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
                if (StringUtil.isNotEmpty(redisHelperValue)) {
                    if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))) {
                        throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
                    }
                }
                SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212032);
                    }
                }
            }
            // 删除装配单的负库存校验
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termsQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID),assembleIdList));
            boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE),InstockTypeEnum.ASSEMBLE_INSTOCK.getCode()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntityExt> instockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));
            List<Long> instockIdIn = new ArrayList<>();
            instockList.forEach((item)->{
                instockIdIn.add(item.getDataId());
            });
            //查询编号
            for(AssembleEntityExt entityExt : assembleList){
                String sheetNo = entityExt.getSerialNo();
                no.add(sheetNo);
                instockIdAndno.put(entityExt.getId(), sheetNo);
            }
            Map<String,Object> instockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            instockProductParam.put("refIdIn", assembleIdList);
            instockProductParam.put("corpid", corpid);
            instockProductParam.put("del", 0);
            instockProductParam.put("type", InstockTypeEnum.ASSEMBLE_INSTOCK.getCode());
            List<InstockProductEntity> instockProductEntityExts = instockProductModel.findEntitys(instockProductParam);
            instockProductParam.put("type", OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode());
            List<OutstockProductEntity> outstockProductEntityExts = outstockProductModel.findEntitys(instockProductParam);
            Set<Long> disableBatchProducts = saasDeleteHelp.checkDocumentDelete(corpid, outstockProductEntityExts, instockProductEntityExts, instockIdAndno);
            Map<String,InstockProductEntity> warehouseKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String,InstockProductEntity> batchKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityExts) {
                entity.setTransferNum(entity.getProductNum());
                if (disableBatchProducts.contains(entity.getParentId())) {
                    String key = entity.getProductId() + "_" + entity.getWarehouseId();
                    if (warehouseKeyMap.containsKey(key)) {
                        InstockProductEntity instockProductEntity = warehouseKeyMap.get(key);
                        instockProductEntity.setTransferNum(Arith.add(instockProductEntity.getTransferNum(),entity.getTransferNum()));
                        warehouseKeyMap.put(key,instockProductEntity);
                    } else {
                        warehouseKeyMap.put(key,entity);
                    }
                } else {
                    String key = formDataValidateProductHelp.getBatchKey(entity.getProductId(), entity.getWarehouseId(), entity.getBatch(), entity.getProduceDate(), entity.getGuaranteePeriod());
                    if (batchKeyMap.containsKey(key)) {
                        InstockProductEntity instockProductEntity = batchKeyMap.get(key);
                        instockProductEntity.setTransferNum(Arith.add(instockProductEntity.getTransferNum(),entity.getTransferNum()));
                        batchKeyMap.put(key,instockProductEntity);
                    } else {
                        batchKeyMap.put(key,entity);
                    }
                }
            }

            instockService.negativeStockCheck(corpid, warehouseKeyMap, batchKeyMap);
            if(!assembleIdList.isEmpty()) {
                if(BasicConstant.ONE.equals(assembleDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(assembleIdList.size())){
                    assembleModel.deleteByKey(assembleIdList.get(0),corpid);
                }else {
                    assembleModel.deleteBatch(assembleIdList, corpid);
                }
            }
            Runnable runnable = () -> {
                try {
                    // 删除装配出入单关联产品
                    Map<String, Object> assembleProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    assembleProductParam.put("corpid", corpid);
                    assembleProductParam.put("assembleIdIn", assembleIdList);
                    List<AssembleProductEntity> assembleProductList = assembleProductModel.findEntitys(assembleProductParam);
                    if (Objects.isNull(assembleProductList)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                    }
                    Set<Long> refIdIn = new HashSet<>();
                    assembleProductList.forEach((item)->{
                        refIdIn.add(item.getId());
                    });
                    AssembleProductDeleteBatchDTO assembleProductDeleteBatchDTO = new AssembleProductDeleteBatchDTO();
                    BeanUtil.copyProperties(assembleDeleteBatchDTO, assembleProductDeleteBatchDTO);
                    assembleProductDeleteBatchDTO.setAssembleIdIn(assembleIdList);
                    assembleProductService.deleteBatch(assembleProductDeleteBatchDTO);
                    // 删除装配单关联产品冗余信息
                    if(!refIdIn.isEmpty()) {
                        ProductBaseInfoDeleteBatchDTO productBaseInfoDeleteBatchDTO = new ProductBaseInfoDeleteBatchDTO();
                        productBaseInfoDeleteBatchDTO.setRefType(XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
                        List<Long> refIdList = new ArrayList<>();
                        refIdIn.forEach((item)->{
                            refIdList.add(item);
                        });
                        productBaseInfoDeleteBatchDTO.setRefIdList(refIdList);
                        productBaseInfoService.deleteBatchByRefId(productBaseInfoDeleteBatchDTO);
                    }
                    // 删除入库单
                    deleteInstockByAssembleId(assembleDeleteBatchDTO, assembleIdList);
                    // 删除出库单
                    deleteOutstockByAssembleId(assembleDeleteBatchDTO, assembleIdList);
                }catch (Exception e) {
                    LOG.error("删除装配出入库单关联数据", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
            // TODO 审批记录
        } catch (XbbException e) {
            LOG.error("assembleServiceImpl.deleteBatch 执行出错：", e);
            throw e;
        }catch (Exception e) {
            LOG.error("assembleServiceImpl.deleteBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
        if (Objects.equals(1, assembleDeleteBatchDTO.getIsBusinessRule())) {
            operateTypeEnum = OperateTypeEnum.RULE_DELETE;
        }
        //生成删除日志(区分单个删除和批量删除)
        String userId = assembleDeleteBatchDTO.getUserId();
        String userName = assembleDeleteBatchDTO.getLoginUserName();
        String nameStr = StringUtils.join(no, "，");
        if(assembleIdList.size() > 1){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.ASSEMBLE.getName(), assembleIdList.size());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(AssembleEnum.SHEET_NO.getAttrName());
            infoArrPojo.setContent(nameStr);
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.ASSEMBLE, operateTypeEnum,
                    "", "", memo, assembleDeleteBatchDTO.getHttpHeader());
        } else if (Objects.equals(assembleIdList.size(), 1)){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.ASSEMBLE.getName(), nameStr);
            mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.ASSEMBLE, operateTypeEnum,
                    assembleIdList.get(0).toString(), nameStr, memo, assembleDeleteBatchDTO.getHttpHeader());
        }

        return assembleDeleteBatchVO;
    }

    @Override
    public void batchEditAttr(AssembleEditAttrUpdateDTO assembleEditAttrUpdateDTO) throws XbbException {
        try {
            List<AssembleUpdateDTO> assembleList = new ArrayList<>();
            assembleEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                AssembleUpdateDTO outstockUpdateDTO = new AssembleUpdateDTO();
                outstockUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(assembleEditAttrUpdateDTO.getFieldEditedList());
                outstockUpdateDTO.setData(data);
                assembleList.add(outstockUpdateDTO);
            });
            List<AssembleEntityExt> assembleEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!assembleList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", assembleEditAttrUpdateDTO.getCorpid());
                param.put("idIn", assembleEditAttrUpdateDTO.getDataIdList());
                assembleEntityList = assembleModel.findEntitys(param);
                if (Objects.isNull(assembleEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                AssembleUpdateBatchDTO assembleUpdateBatchDTO = new AssembleUpdateBatchDTO();
                BeanUtil.copyProperties(assembleEditAttrUpdateDTO, assembleUpdateBatchDTO);
                assembleUpdateBatchDTO.setAssembleList(assembleList);
                updateBatch(assembleUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (AssembleEntityExt item : assembleEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = assembleEditAttrUpdateDTO.getUserId();
            String corpid = assembleEditAttrUpdateDTO.getCorpid();
            String loginUserName = assembleEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = assembleEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = assembleEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence,assembleEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(assembleEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.ASSEMBLE.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.ASSEMBLE.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.ASSEMBLE, OperateTypeEnum.EDIT,
                        "", "", memo, assembleEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.ASSEMBLE.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.ASSEMBLE, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, assembleEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("assembleService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /*@Override
    public BusinessProductListVO getAssembleProductList(BusinessProductListDTO businessProductListDTO, Object object) throws XbbException {
        BusinessProductListVO businessProductListVO = new BusinessProductListVO();
        try {
            String corpid = businessProductListDTO.getCorpid();
            Long refId = businessProductListDTO.getDataId();
            AssembleEntityExt assembleEntityExt = assembleModel.getByKey(refId, corpid);
            if (Objects.isNull(assembleEntityExt)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("assembleId", businessProductListDTO.getDataId());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.PAGE,  businessProductListDTO.getPage());
            PageHelper pageHelper = PageHelperUtil.getPageHelper(param, assembleProductModel, businessProductListDTO.getPageSize());
            List<AssembleProductEntity> assembleProductList = (List<AssembleProductEntity>)PageHelperUtil.getEntityList(param, pageHelper, assembleProductModel);
            if (Objects.isNull(assembleProductList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }

            // 用于存放当前启用的产品模板解释的map
            Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            saasAddHelp.getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, null);

            Set<Long> assembleProductIds = new HashSet<>();
//            Set<Long> assembleWarehouseIds = new HashSet<>();
            Set<Long> productIds = new HashSet<>();
            Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (AssembleProductEntity assembleProductEntity : assembleProductList) {
                assembleProductIds.add(assembleProductEntity.getId());
//                assembleWarehouseIds.add(assembleProductEntity.getWarehouseId());
                productIds.add(assembleProductEntity.getProductId());
                warehouseKeySet.add(assembleProductEntity.getProductId() + "_" + assembleProductEntity.getWarehouseId());
            }
            param.clear();
            param.put("corpid", corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("refIdIn", assembleProductIds);
            param.put("refType", XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
            //装配单关联产品冗余信息
            List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.findEntitys(param);
            if (Objects.isNull(productBaseInfoList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<Long, ProductBaseInfoEntity> productBaseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProductBaseInfoEntity productBaseInfo : productBaseInfoList) {
                productBaseInfoMap.put(productBaseInfo.getRefId(), productBaseInfo);
            }
            // 仓库
            param.clear();
            param.put("corpid", corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
//            param.put("warehouseIdIn", assembleWarehouseIds);
//            param.put("productIdIn", productIds);
            param.put("warehouseKeyIn",warehouseKeySet);
            List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param,null);
            if (Objects.isNull(productWarehouseList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            // 出库单产品对应仓库信息
            Map<Long, JSONObject> warehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, ProductWarehouseEntity> productWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProductWarehouseEntity item : productWarehouseList) {
                productWarehouseMap.put(item.getProductId(), item);
                JSONObject warehouse = new JSONObject();
                warehouse.put("id", item.getWarehouseId());
                warehouse.put("value", item.getWarehouseName());
                warehouseMap.put(item.getWarehouseId(), warehouse);
            }
            // 产品
            Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds,corpid,null);
//            Integer numPrecision = companyConfigService.getNumberPrecision(corpid);
            FieldAttrEntity numFieldAttrEntity = new FieldAttrEntity();
            if(nowProductExplainMap.containsKey(ProductEnum.STOCK.getSaasAttr())) {
                numFieldAttrEntity = nowProductExplainMap.get(ProductEnum.STOCK.getSaasAttr());
            }
            Integer numPrecision = numFieldAttrEntity.getAccuracy();
            Map<Integer, JSONObject> outstockProductSortMap = new TreeMap<>();
            Map<Integer, JSONObject> instockProductSortMap = new TreeMap<>();
            for (AssembleProductEntity item : assembleProductList) {
                FormatRelativeProductEntityExt formatProduct = new FormatRelativeProductEntityExt();
                Long productId = item.getProductId();
                formatProduct.setParentId(item.getParentId());
                formatProduct.setProductId(productId);
                formatProduct.setRefId(refId);
                Long assembleProductId = item.getId();
                String specification = item.getProductSpecification();
                formatProduct.setProductSpecification(specificationModel.joinSpecification(specification));
                formatProduct.setProductName(item.getProductName());
                formatProduct.setProductNo(item.getProductNo());
                formatProduct.setBarcode(item.getBarcode());
                formatProduct.setWarehouseId(item.getWarehouseId());
                formatProduct.setProductNum(item.getProductNum());
                formatProduct.setWarehouseObj(warehouseMap.get(item.getWarehouseId()));
                ProductStockInfoEntity productStockInfoEntity = new ProductStockInfoEntity();
                Double productStock = 0.0;
                if (Objects.nonNull(item.getWarehouseId()) && !Objects.equals(item.getWarehouseId(), 0L)) {
                    if (productBaseInfoMap.containsKey(assembleProductId)) {
                        ProductBaseInfoEntity productBaseInfoEntity = productBaseInfoMap.get(assembleProductId);
                        BeanUtil.copyProperties(productBaseInfoEntity, productStockInfoEntity);
                        productStockInfoEntity.setBatch(productBaseInfoEntity.getBatch());
                        productStockInfoEntity.setProduceDate(productBaseInfoEntity.getProduceDate());
                        productStockInfoEntity.setGuaranteePeriod(productBaseInfoEntity.getGuaranteePeriod());
                        formatProduct.setMemo(productBaseInfoEntity.getMemo());
                        formatProduct.setProductStockInfoEntity(productStockInfoEntity);
                        String batch = productBaseInfoEntity.getBatch();
                        // 判断有没有批次信息

                        if (StringUtil.isNotEmpty(batch)) {
                            // 获取该批次产品在当前仓库下的库存
                            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            params.put("corpid", corpid);
                            params.put("del", 0);
                            params.put("productId", productId);
                            params.put("warehouseId", item.getWarehouseId());
                            params.put("batch", batch);
//                            List<ProductStockInfoEntity> productStockList = productStockInfoService.getValidBatchInfoList(corpid, params);
                            List<ProductStockEntity> productStockEntityList = productStockModel.getValidBatchInfoList(Collections.singletonList(productId),corpid,item.getWarehouseId(),batch, Collections.singletonList("num"));
                            for (ProductStockEntity stockInfo : productStockEntityList) {
                                if (stockInfo.getNum() != null) {
                                    productStock += stockInfo.getNum();
                                }
                            }
                        } else {
                            ProductWarehouseEntity productWarehouse = productWarehouseMap.get(productId);
                            if (productWarehouse != null) {
                                // 产品仓库库存
                                productStock = productWarehouse.getNum();
                            }
                        }
                    }
                } else {
                    if (productMap.containsKey(productId)) {
                        PaasFormDataEntityExt product = productMap.get(productId);
                        JSONObject data = product.getData();
                        if (Objects.nonNull(data)) {
                            productStock = data.getDouble(ProductEnum.STOCK.getAttr()) == null ? 0 : data.getDouble(ProductEnum.STOCK.getAttr());
                        }
                    }
                }
                formatProduct.setStock(productStock);
                // 成本
                formatProduct.setCost(item.getCost());
                Double productNum = item.getProductNum();
                productNum = attrDecimalPrecisionHelper.setPrecision(productNum, numPrecision);
                formatProduct.setProductNum(productNum);
                formatProduct.setProductUnit(item.getProductUnit());
                if (productMap.get(productId) != null) {
                    // 设置产品图片
                    JSONObject data = productMap.get(productId).getData();
                    if(Objects.nonNull(data)){
                        String imageUrl = "";
                        JSONArray jsonArray = data.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
                        if (Objects.nonNull(jsonArray) && !jsonArray.isEmpty()){
                            imageUrl = jsonArray.getString(jsonArray.size()-1);
                        }
                        formatProduct.setImageUrl(imageUrl);
                    }
                }
                FormatRelativeProductDTO formatRelativeProductDTO = new FormatRelativeProductDTO();
                BeanUtil.copyProperties(businessProductListDTO, formatRelativeProductDTO);
                formatRelativeProductDTO.setBusinessType(XbbRefTypeEnum.ASSEMBLE.getCode());
                formatRelativeProductDTO.setTargetBusinessType(businessProductListDTO.getBusinessType());
                formatRelativeProductDTO.setCorpid(corpid);
                formatRelativeProductDTO.setNowProductExplainMap(nowProductExplainMap);
                formatRelativeProductDTO.setFormatRelativeProductEntityExt(formatProduct);
                JSONObject productObj = productService.getFormatProductJsonArray(formatRelativeProductDTO);
                // 出库产品和入库产品
                if (Objects.equals(item.getType(), 1)){
                    outstockProductSortMap.put(item.getSort(), productObj);
                } else {
                    instockProductSortMap.put(item.getSort(), productObj);
                }

            }
            // 返回给前端的接受对象
            JSONObject outstockProductObj = new JSONObject();
            JSONArray outstockProduct = new JSONArray();
            outstockProduct.addAll(outstockProductSortMap.values());
            outstockProductObj.put(StringConstant.PRODUCT_LIST, outstockProduct);
            outstockProductObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, AssembleEnum.OUT_PRODUCTS.getAttr());
            outstockProductObj.put(BusinessConstant.EXPLAINS, saasGetHelp.getSelectProductExplains(XbbRefTypeEnum.ASSEMBLE, businessProductListDTO.getBusinessType(), corpid,
                    AssembleEnum.OUT_PRODUCTS.getAttr()));
            businessProductListVO.setOutstockProduct(outstockProductObj);

            JSONObject instockProductObj = new JSONObject();
            JSONArray instockProduct = new JSONArray();
            instockProduct.addAll(instockProductSortMap.values());
            instockProductObj.put(StringConstant.PRODUCT_LIST, instockProduct);
            instockProductObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, AssembleEnum.IN_PRODUCTS.getAttr());
            instockProductObj.put(BusinessConstant.EXPLAINS, saasGetHelp.getSelectProductExplains(XbbRefTypeEnum.ASSEMBLE, businessProductListDTO.getBusinessType(), corpid,
                    AssembleEnum.IN_PRODUCTS.getAttr()));
            businessProductListVO.setInstockProduct(instockProductObj);
            businessProductListVO.setPageHelper(pageHelper);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("assembleService.getAssembleProductList 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return businessProductListVO;
    }*/

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        // data 数据
        JSONObject dataJson = new JSONObject();

        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);

        // 遍历数据
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);

            if (Objects.equals(attr, AssembleEnum.IN_PRODUCTS.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttrEntityForImport, XbbRefTypeEnum.ASSEMBLE.getCode(), corpid);
            } else if (Objects.equals(attr, AssembleEnum.OUT_PRODUCTS.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttrEntityForImport, XbbRefTypeEnum.ASSEMBLE.getCode(), corpid);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else if (Objects.equals(attr, AssembleEnum.MANAGER_ID.getAttr())) {
                importHelper.formatOwnId4Import(formDataAddDTO, fieldAttrEntityForImport, cellValue);
            } else if (Objects.equals(attr, AssembleEnum.OUT_WAREHOUSE_ID.getAttr()) || Objects.equals(attr, AssembleEnum.INTO_WAREHOUSE_ID.getAttr())) {
                importHelper.formatWareHouse4Import(dataJson, fieldAttrEntityForImport, attr, cellValue);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200022);
                }
                formDataAddDTO.setSerialNo(cellValue.toString());
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        // 所有入库产品
        List<Long> idList = new ArrayList<>();
        paasFormDataESList.forEach(item -> idList.add(item.getDataId()));
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<ProductEntityExt> productList = productModel.findEntitys(params);
        Map<Long, ProductEntityExt> productMap = new HashMap<>();
        productList.forEach(item -> productMap.put(item.getId(), item));
        // 装配关联入库产品map
        params.put("assembleIdIn", idList);
        params.put("type", 2);
        params.put("orderByStr","sort");
        List<AssembleProductEntity> inProductList = assembleProductModel.findEntitys(params);
        Map<Long, List<AssembleProductEntity>> inAssembleProductMap = new HashMap<>();
        inProductList.forEach(item -> {
            Long refId = item.getAssembleId();
            if (inAssembleProductMap.containsKey(refId)) {
                inAssembleProductMap.get(refId).add(item);
            } else {
                List<AssembleProductEntity> productEntityList = new ArrayList<>();
                productEntityList.add(item);
                inAssembleProductMap.put(refId, productEntityList);
            }
        });
        // 装配关联出库产品map
        params.put("type", 1);
        List<AssembleProductEntity> outProductList = assembleProductModel.findEntitys(params);
        Map<Long, List<AssembleProductEntity>> outAssembleProductMap = new HashMap<>();
        outProductList.forEach(item -> {
            Long refId = item.getAssembleId();
            if (outAssembleProductMap.containsKey(refId)) {
                outAssembleProductMap.get(refId).add(item);
            } else {
                List<AssembleProductEntity> productEntityList = new ArrayList<>();
                productEntityList.add(item);
                outAssembleProductMap.put(refId, productEntityList);
            }
        });

        // 所有仓库map
        params.remove("assembleIdIn");
        params.remove("type");
        params.remove("orderByStr");
        List<WarehouseEntityExt> warehouseList = warehouseModel.findEntitys(params);
        Map<Long, WarehouseEntityExt> warehouseMap = new HashMap<>();
        warehouseList.forEach(item -> warehouseMap.put(item.getId(), item));

        // 库存信息map
        params.put("refType", XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
        List<ProductBaseInfoEntity> assembleInfoList = productBaseInfoModel.findEntitys(params);
        Map<Long, ProductBaseInfoEntity> assembleInfoMap = new HashMap<>();
        List<String> batchIdList = new ArrayList<>();
        assembleInfoList.forEach(item -> {
            assembleInfoMap.put(item.getRefId(), item);
            batchIdList.add(item.getBatch());
        });

        // 分仓库存
        Set<Long> warehouseIdList = new HashSet<>();
        Set<Long> productIdList = new HashSet<>();
        for (AssembleProductEntity assembleProductEntity : inProductList) {
            Long productId = assembleProductEntity.getProductId();
            Long warehouseId = assembleProductEntity.getWarehouseId();
            warehouseIdList.add(warehouseId);
            productIdList.add(productId);
        }

        for (AssembleProductEntity assembleProductEntity : outProductList) {
            Long productId = assembleProductEntity.getProductId();
            Long warehouseId = assembleProductEntity.getWarehouseId();
            warehouseIdList.add(warehouseId);
            productIdList.add(productId);
        }


        // 出入库产品，出入库库存产品
        FieldAttrEntityForImport outProductFieldAttr = new FieldAttrEntityForImport();
        FieldAttrEntityForImport inProductFieldAttr = new FieldAttrEntityForImport();
        for (FieldAttrEntityForImport item : fieldAttrList) {
            if (Objects.equals(item.getAttr(), AssembleEnum.OUT_PRODUCTS.getAttr())) {
                outProductFieldAttr = item;
            } else if (Objects.equals(item.getAttr(), AssembleEnum.IN_PRODUCTS.getAttr())) {
                inProductFieldAttr = item;
            }
        }
        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());

        // 暂时只处理产品
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject formDataObj = paasFormDataEntityExt.getData();
            Long dataId = paasFormDataEntityExt.getDataId();

            String inProductAttr = inProductFieldAttr.getAttr();

            String outProductAttr = outProductFieldAttr.getAttr();

            List<AssembleProductEntity> outAssembleProductList = outAssembleProductMap.get(dataId);
            List<AssembleProductEntity> inAssembleProductList = inAssembleProductMap.get(dataId);
            if (inAssembleProductList == null || inAssembleProductList.size() == 0 || outAssembleProductList == null || outAssembleProductList.size() == 0) {
                formDataObj.put(inProductAttr, new JSONArray());
                formDataObj.put(outProductAttr, new JSONArray());
                continue;
            }
            JSONArray inProductArray = new JSONArray();
            for (AssembleProductEntity assembleProductEntity : inAssembleProductList) {
                Long productId = assembleProductEntity.getProductId();
                Double num = assembleProductEntity.getProductNum();
                Long warehouseId = assembleProductEntity.getWarehouseId();
                if (Objects.nonNull(assembleProductEntity.getPriceData()) && assembleProductEntity.getPriceData().size() > BasicConstant.ZERO){
                    assembleProductEntity.getData().putAll(assembleProductEntity.getPriceData());
                }
                // 产品信息转换
                JSONObject productObj = assembleProductEntity.getData() == null ? new JSONObject() : assembleProductEntity.getData();
                importHelper.formatProduct4Export(productMap, warehouseMap, productId, num, warehouseId, productObj);
                if (Objects.isNull(productObj.get(AssembleInProductEnum.COST.getAttr()))) {
                    productObj.put(AssembleInProductEnum.COST.getAttr(), assembleProductEntity.getCost());
                }
                importHelper.formatBatch4Export(productObj);
                //基本单位时直接塞入productUnit
                if (Objects.isNull(assembleProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        assembleProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), assembleProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), assembleProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), assembleProductEntity.getBusinessNum());
                    productObj.put(AssembleInProductEnum.COST.getAttr(), assembleProductEntity.getData().get(AssembleInProductEnum.COST.getAttr()));
                }

                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), assembleProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  assembleProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                inProductArray.add(productObj);
            }
            formDataObj.put(inProductAttr, inProductArray);

            JSONArray outProductArray = new JSONArray();
            for (AssembleProductEntity assembleProductEntity : outAssembleProductList) {
                Long productId = assembleProductEntity.getProductId();
                Double num = assembleProductEntity.getProductNum();
                Long warehouseId = assembleProductEntity.getWarehouseId();
                if (Objects.nonNull(assembleProductEntity.getPriceData()) && assembleProductEntity.getPriceData().size() > BasicConstant.ZERO){
                    assembleProductEntity.getData().putAll(assembleProductEntity.getPriceData());
                }
                // 产品信息转换
                JSONObject productObj = assembleProductEntity.getData() == null ? new JSONObject() : assembleProductEntity.getData();
                importHelper.formatProduct4Export(productMap, warehouseMap, productId, num, warehouseId, productObj);
                if (Objects.isNull(productObj.get(AssembleInProductEnum.COST.getAttr()))) {
                    productObj.put(AssembleInProductEnum.COST.getAttr(), assembleProductEntity.getCost());
                }
                importHelper.formatBatch4Export(productObj);
                //基本单位时直接塞入productUnit
                if (Objects.isNull(assembleProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        assembleProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), assembleProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), assembleProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), assembleProductEntity.getBusinessNum());
                    productObj.put(AssembleInProductEnum.COST.getAttr(), assembleProductEntity.getData().get(AssembleInProductEnum.COST.getAttr()));
                }

                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), assembleProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  assembleProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                outProductArray.add(productObj);
                /*// 库存产品信息转换
                ProductBaseInfoEntity stockInfoEntity = assembleInfoMap.get(assembleProductEntity.getId());
                importHelper.formatBaseInfo4Export(productObj, stockInfoEntity);*/
            }
            formDataObj.put(outProductAttr, outProductArray);
        }
    }

    private void updateBatch(AssembleUpdateBatchDTO assembleUpdateBatchDTO) throws XbbException {
        try {
            List<UpdateDataEntity> updateDataList = new ArrayList<>();
            String corpid = assembleUpdateBatchDTO.getCorpid();
            assembleUpdateBatchDTO.getAssembleList().forEach((item)->{
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid);
                updateDataList.add(updateDataEntity);
            });
            if (!updateDataList.isEmpty()) {
                assembleModel.updateBatch(updateDataList, corpid);
            }
        } catch (Exception e) {
            LOG.error("assembleService.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 删除入库单
     * @author 吴峰
     * @date 2019/3/5 20:56
     * @param assembleDeleteBatchDTO
     * @param assembleIdList
     * @return void
     * @throws XbbException 业务异常
     */
    private void deleteInstockByAssembleId(AssembleDeleteBatchDTO assembleDeleteBatchDTO, List<Long> assembleIdList) throws XbbException {
        try {
            // 删除入库单
            InstockListDTO instockListDTO = new InstockListDTO();
            BeanUtil.copyProperties(assembleDeleteBatchDTO, instockListDTO);
            instockListDTO.setRefIdIn(assembleIdList);
            instockListDTO.setType(InstockTypeEnum.ASSEMBLE_INSTOCK.getCode());
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            instockListDTO.setFieldList(fieldList);
            InstockListVO instockListVO = instockService.findInstockList(instockListDTO);
            if (Objects.isNull(instockListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            Set<Long> instockIdIn = new HashSet<>();
            instockListVO.getInstockList().forEach((item)->{
                instockIdIn.add(item.getDataId());
            });
            if (!instockIdIn.isEmpty()) {
                List<Long> instockIdList = new ArrayList<>();
                instockIdIn.forEach((item)->{
                    instockIdList.add(item);
                });
                InstockDeleteBatchDTO instockDeleteBatchDTO = new InstockDeleteBatchDTO();
                BeanUtil.copyProperties(assembleDeleteBatchDTO, instockDeleteBatchDTO);
                instockDeleteBatchDTO.setDataIdList(instockIdList);
                instockDeleteBatchDTO.setBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode());
                instockService.deleteBatch(instockDeleteBatchDTO);
            }
        } catch (XbbException e) {
            LOG.error("assembleServiceImpl.deleteInstockByAssembleId 执行出错：", e);
            throw e;
        }catch (Exception e) {
            LOG.error("assembleServiceImpl.deleteInstockByAssembleId 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 删除入库单
     * @author 吴峰
     * @date 2019/3/5 20:56
     * @param assembleDeleteBatchDTO
     * @param assembleIdList
     * @return void
     * @throws XbbException 业务异常
     */
    private void deleteOutstockByAssembleId(AssembleDeleteBatchDTO assembleDeleteBatchDTO, List<Long> assembleIdList) throws XbbException {
        try {
            // 删除入库单
            OutStockListDTO outStockListDTO = new OutStockListDTO();
            BeanUtil.copyProperties(assembleDeleteBatchDTO, outStockListDTO);
            outStockListDTO.setRefIdIn(assembleIdList);
            outStockListDTO.setType(OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode());
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            outStockListDTO.setFieldList(fieldList);
            OutStockListVO outStockListVO = outstockService.findOutstockList(outStockListDTO);
            if (Objects.isNull(outStockListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            Set<Long> outstockIdIn = new HashSet<>();
            outStockListVO.getOutstockList().forEach((item)->{
                outstockIdIn.add(item.getDataId());
            });
            if (!outstockIdIn.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>(outstockIdIn);

                OutstockDeleteBatchDTO outstockDeleteBatchDTO = new OutstockDeleteBatchDTO();
                BeanUtil.copyProperties(assembleDeleteBatchDTO, outstockDeleteBatchDTO);
                outstockDeleteBatchDTO.setDataIdList(outstockIdList);
                outstockDeleteBatchDTO.setBusinessType(XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
                outstockService.deleteBatch(outstockDeleteBatchDTO);
            }
        } catch (XbbException e) {
            LOG.error("assembleServiceImpl.deleteOutstockByAssembleId 执行出错：", e);
            throw e;
        }catch (Exception e) {
            LOG.error("assembleServiceImpl.deleteOutstockByAssembleId 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }




    /**
     * 采购退货单根据传入参数将冗余数据存入data中，方便使用时获取
     *
     * @param validateDataDTO 前端传参数据
     * @throws XbbException 参数不符合要求错误提醒
     * @author Jian.Wang
     * @date 2019/2/21 10:04
     * @since v1.0
     */
    private void redundantDataProcessing(ValidateDataDTO validateDataDTO) throws XbbException{
        JSONObject data = validateDataDTO.getData();
        if (data == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
        // 存入创建者ID和创建者名称
//        String userId = validateDataDTO.getUserId();
//        String userName = validateDataDTO.getLoginUserName();
//        data.put(AssembleEnum.CREATOR_ID.getAttr(),userId);
//        data.put(AssembleEnum.CREATOR_NAME.getAttr(),userName);

        validateDataDTO.setData(data);
    }

    /**
     *
     * 生成出入库单
     * @param saasFormSaveDTO 数据
     * @author Jian.Wang
     * @date 2019/2/23 15:05
     * @since v1.0
     *
     */
    @Deprecated
    private void generateStockSheet(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        // 生成出库单
        generateOutStockSheet(saasFormSaveDTO);
        // 生成入库单
        generateInStockSheet(saasFormSaveDTO);
    }

    /**
     * 生成入库单
     * @param saasFormSaveDTO 数据
     */
    @Deprecated
    private void generateInStockSheet(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long assembleId = newPaasFormDataEntity.getId();
        String corpid = saasFormSaveDTO.getCorpid();
        JSONObject newData = saasFormSaveDTO.getNewData();
        // 入库产品
        JSONArray instockProductArray = newData.getJSONArray(AssembleEnum.IN_PRODUCTS.getAttr());
        // 判断是否已经生成入库单
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(InstockEnum.getAttrConnectData(InstockEnum.REF_ID), assembleId));
        boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.ASSEMBLE_INSTOCK.getCode()));
        List<PaasFormDataEntityExt> paasFormDataEntityExts = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, null);
        InstockEntityExt instock = new InstockEntityExt();
        JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(newData, AssembleEnum.IN_PRODUCTS.getAttr());
        // 获取字段解释信息
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode(), corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        FieldAttrEntity linkProductField = new FieldAttrEntity();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (InstockEnum.PRODUCT.getAttr().equals(fieldAttrEntity.getAttr())) {
                linkProductField = fieldAttrEntity;
                break;
            }
        }
        if (paasFormDataEntityExts.isEmpty()) {
            instock.setCorpid(corpid);
            BeanUtil.copyProperties(paasFormExplainEntity, instock);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            // 获取流水号
            String serialNo = saasSaveHelp.getSerialNo(explainList, paasFormExplainEntity.getFormId(), corpid);
            instock.setSerialNo(serialNo);
            instock.setOwnerId(newPaasFormDataEntity.getCreatorId());
            instock.setDepartmentId(0L);
            instock.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
            instock.setCreatorId(newPaasFormDataEntity.getCreatorId());
            JSONObject instockData = new JSONObject();
            instockData.put(InstockEnum.WAREHOUSE_ID.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, AssembleEnum.INTO_WAREHOUSE_ID.getAttr(), 0L));
            instockData.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
            instockData.put(InstockEnum.TYPE.getAttr(), Objects.toString(InstockTypeEnum.ASSEMBLE_INSTOCK.getCode()));
            instockData.put(InstockEnum.REF_ID.getAttr(), assembleId);
            instockData.put(InstockEnum.REF_ID_LINKED_TEXT.getAttr(), newPaasFormDataEntity.getSerialNo());
            if (explainMap.containsKey(InstockEnum.TIME.getAttr())) {
                String dateType = explainMap.get(InstockEnum.TIME.getAttr()).getDateType();
                instockData.put(InstockEnum.TIME.getAttr(), DateTimeUtil.getThisIntByDateType(dateType));
            } else {
                instockData.put(InstockEnum.TIME.getAttr(), DateTimeUtil.getTodayInt());
            }
//            instockData.put(InstockEnum.INCOMING.getAttr(), BasicConstant.ZERO);
            instockData.put(InstockEnum.MEMO.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.MEMO.getAttr(), ""));
//            saasSaveHelp.formatSelectProduct4Save(newData, AssembleEnum.IN_PRODUCTS.getAttr());
            instockData.put(InstockEnum.PRODUCT.getAttr(), newData.getJSONArray(AssembleEnum.IN_PRODUCTS.getAttr()));
            instock.setId(null);
            instock.setData(instockData);
            instockModel.save(instock);
        } else {
            PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExts.get(BasicConstant.ZERO);
            BeanUtil.copyProperties(paasFormDataEntityExt, instock);
        }
        DefaultAttrPoJo defaultAttr = linkProductField.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        // 获取关联产品联动关系
        LinkProductRelyEntity linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, InstockEnum.PRODUCT.getAttr(), paasFormExplainEntity.getFormId(), XbbRefTypeEnum.ASSEMBLE.getCode(), DelEnum.NORMAL.getDel());
        if (Objects.nonNull(defaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(defaultType) && Objects.nonNull(linkProductRelyEntity)) {
            // 源单解释
            Map<String, FieldAttrEntity> sourceExplainMap;
            // 当前表单解释
            Map<String, FieldAttrEntity> thisExplainMap;
            // 当前表单某个关联产品解释
            Map<String, FieldAttrEntity> subThisExplainMap;
            // 源单某个关联产品解释
            Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 当前表单某个关联产品子字段与源单某个关联产品对应关系
            Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(saasFormSaveDTO, userAndDepartmentGetDTO);
            UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
            // 源数据表单
            PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity>  sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
            // 当前表单
            thisExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(InstockEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (Object object : instockProductArray) {
                JSONObject assembleProductData = (JSONObject) object;
                if (!thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(assembleProductData);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    Iterator<String> iterator = thisToTarget.keySet().iterator();
                    while (iterator.hasNext()) {
                        String thisKey = iterator.next();
                        // 获取对应的字段
                        String key = thisToTarget.get(thisKey);
                        if (Objects.isNull(assembleProductData.get(key))) {
                            continue;
                        }
                        FieldAttrEntity displayField = subThisExplainMap.get(thisKey);
                        if (Objects.isNull(displayField)) {
                            continue;
                        }
                        Integer thisKeyFieldType = displayField.getFieldType();
                        if (FieldTypeEnum.CHECKBOX_GROUP.getType().equals(thisKeyFieldType) || FieldTypeEnum.COMBO_CHECK.getType().equals(thisKeyFieldType)) {
                            JSONArray jsonArray = thisData.getJSONArray(thisKey);
                            JSONArray objects = new JSONArray();
                            for (int i = 0; i < jsonArray.size(); i++) {
                                JSONObject itemJSON = jsonArray.getJSONObject(i);
                                Object text = itemJSON.get("text");
                                objects.add(text);
                            }
                            thisData.put(thisKey, objects);
                        } else if (FieldTypeEnum.COMBO.getType().equals(thisKeyFieldType) || FieldTypeEnum.RADIO_GROUP.getType().equals(thisKeyFieldType)){
                            JSONObject itemJSON = thisData.getJSONObject(thisKey);
                            thisData.put(thisKey, itemJSON.get("text"));
                        } else if (FieldTypeEnum.USER_GROUP.getType().equals(thisKeyFieldType) || FieldTypeEnum.DEPT_GROUP.getType().equals(thisKeyFieldType)) {
                            JSONArray jsonArray = thisData.getJSONArray(thisKey);
                            JSONArray objects = new JSONArray();
                            for (int i = 0; i < jsonArray.size(); i++) {
                                JSONObject itemJSON = jsonArray.getJSONObject(i);
                                Object text = itemJSON.get("id");
                                objects.add(text);
                            }
                            thisData.put(thisKey, objects);
                        } else if (FieldTypeEnum.USER.getType().equals(thisKeyFieldType) || FieldTypeEnum.DEPT.getType().equals(thisKeyFieldType)) {
                            JSONObject itemJSON = thisData.getJSONObject(thisKey);
                            thisData.put(thisKey, itemJSON.get("id"));
                        }
                    }
                    for (int i = 0; i < productArray.size(); i++) {
                        JSONObject jsonObject = productArray.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(SelectProductEnum.PRODUCT.getAttr()), assembleProductData.getLongValue(SelectProductEnum.PRODUCT.getAttr()))) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }

            }
        }
        instock.getData().put(InstockEnum.PRODUCT.getAttr(),productArray);
        instock.getData().put(InstockEnum.TYPE.getAttr(),InstockTypeEnum.ASSEMBLE_INSTOCK.getCode());
        SaasFormSaveDTO instockSaasFormSaveDTO = new SaasFormSaveDTO();
        BeanUtil.copyProperties(saasFormSaveDTO,instockSaasFormSaveDTO);
        instockSaasFormSaveDTO.setNewData(instock.getData());
        instockSaasFormSaveDTO.setNewPaasFormDataEntity(instock);
        instockSaasFormSaveDTO.setIsNew(true);
        instockSaasFormSaveDTO.setBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode());
        instockService.afterSave(instockSaasFormSaveDTO);
//        }
    }
    /**
     * 生成出库单
     * @param saasFormSaveDTO 数据
     * @date 2019/3/4 14:37
     */
    @Deprecated
    private void generateOutStockSheet(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long assembleId = newPaasFormDataEntity.getId();
        String corpid = saasFormSaveDTO.getCorpid();
        JSONObject newData = saasFormSaveDTO.getNewData();
        //
        JSONArray outstockProductArray = newData.getJSONArray(AssembleEnum.OUT_PRODUCTS.getAttr());
        // 判断是否已经生成入库单
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(OutstockEnum.getAttrConnectData(OutstockEnum.REF_ID), assembleId));
        boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE), OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode()));
        List<PaasFormDataEntityExt> paasFormDataEntityExts = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, null);
        OutstockEntityExt outStock = new OutstockEntityExt();
        JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(newData, AssembleEnum.OUT_PRODUCTS.getAttr());
        // 获取字段解释信息
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(), corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        FieldAttrEntity linkProductField = new FieldAttrEntity();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (OutstockEnum.PRODUCT.getAttr().equals(fieldAttrEntity.getAttr())) {
                linkProductField = fieldAttrEntity;
                break;
            }
        }
        if (paasFormDataEntityExts.isEmpty()) {
            outStock.setCorpid(corpid);
            BeanUtil.copyProperties(paasFormExplainEntity, outStock);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            // 获取流水号
            String serialNo = saasSaveHelp.getSerialNo(explainList, paasFormExplainEntity.getFormId(), corpid);
            outStock.setSerialNo(serialNo);
            outStock.setOwnerId(newPaasFormDataEntity.getCreatorId());
            outStock.setDepartmentId(0L);
            outStock.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
            outStock.setCreatorId(newPaasFormDataEntity.getCreatorId());
            JSONObject outStockData = new JSONObject();
            outStockData.put(OutstockEnum.WAREHOUSE_ID.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, AssembleEnum.OUT_WAREHOUSE_ID.getAttr(), 0L));
            outStockData.put(OutstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
            outStockData.put(OutstockEnum.TYPE.getAttr(), Objects.toString(OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode()));
            outStockData.put(OutstockEnum.REF_ID.getAttr(), assembleId);
            outStockData.put(OutstockEnum.REF_ID_LINKED_TEXT.getAttr(), newPaasFormDataEntity.getSerialNo());
            if (explainMap.containsKey(OutstockEnum.TIME.getAttr())) {
                String dateType = explainMap.get(OutstockEnum.TIME.getAttr()).getDateType();
                outStockData.put(OutstockEnum.TIME.getAttr(), DateTimeUtil.getThisIntByDateType(dateType));
            } else {
                outStockData.put(OutstockEnum.TIME.getAttr(), DateTimeUtil.getTodayInt());
            }
//            outStockData.put(OutstockEnum.OUTBOUND.getAttr(), BasicConstant.ZERO);
            outStockData.put(OutstockEnum.MEMO.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.MEMO.getAttr(), ""));
            //类似于复制
//            saasSaveHelp.formatSelectProduct4Save2(newData, AssembleEnum.OUT_PRODUCTS.getAttr());
//             JSONArray productArray = formDataValidateProductHelp.otherProductToAnother(newData,assemble,ContractEnum.PRODUCT.getAttr(),SalesOpportunityEnum.PRODUCTS.getAttr(),corpid);
            outStockData.put(OutstockEnum.PRODUCT.getAttr(), newData.getJSONArray(AssembleEnum.OUT_PRODUCTS.getAttr()));
            outStock.setId(null);
            outStock.setData(outStockData);
            outstockModel.save(outStock);
        } else {
            PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExts.get(BasicConstant.ZERO);
            BeanUtil.copyProperties(paasFormDataEntityExt, outStock);
        }
//        JSONArray productArray = saasFormSaveDTO.getNewData().getJSONArray(AssembleEnum.OUT_PRODUCTS.getAttr());
        DefaultAttrPoJo defaultAttr = linkProductField.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        // 获取关联产品联动关系
        LinkProductRelyEntity linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, OutstockEnum.PRODUCT.getAttr(), paasFormExplainEntity.getFormId(), XbbRefTypeEnum.ASSEMBLE.getCode(), DelEnum.NORMAL.getDel());
        if (Objects.nonNull(defaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(defaultType) && Objects.nonNull(linkProductRelyEntity)) {
            // 源单解释
            Map<String, FieldAttrEntity> sourceExplainMap;
            // 当前表单解释
            Map<String, FieldAttrEntity> thisExplainMap;
            // 当前表单某个关联产品解释
            Map<String, FieldAttrEntity> subThisExplainMap;
            // 源单某个关联产品解释
            Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 当前表单某个关联产品子字段与源单某个关联产品对应关系
            Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(saasFormSaveDTO, userAndDepartmentGetDTO);
            UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
            // 源数据表单
            PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
            // 当前表单
            thisExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(OutstockEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (Object o : outstockProductArray) {
                JSONObject assembleProductData = (JSONObject) o;
                if (!thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(assembleProductData);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    Iterator<String> iterator = thisToTarget.keySet().iterator();
                    while (iterator.hasNext()) {
                        String thisKey = iterator.next();
                        // 获取对应的字段
                        String key = thisToTarget.get(thisKey);
                        if (Objects.isNull(assembleProductData.get(key))) {
                            continue;
                        }
                        FieldAttrEntity displayField = subThisExplainMap.get(thisKey);
                        if (Objects.isNull(displayField)) {
                            continue;
                        }
                        Integer thisKeyFieldType = displayField.getFieldType();
                        if (FieldTypeEnum.CHECKBOX_GROUP.getType().equals(thisKeyFieldType) || FieldTypeEnum.COMBO_CHECK.getType().equals(thisKeyFieldType)) {
                            JSONArray jsonArray = thisData.getJSONArray(thisKey);
                            JSONArray objects = new JSONArray();
                            for (int i = 0; i < jsonArray.size(); i++) {
                                JSONObject itemJSON = jsonArray.getJSONObject(i);
                                Object text = itemJSON.get("text");
                                objects.add(text);
                            }
                            thisData.put(thisKey, objects);
                        } else if (FieldTypeEnum.COMBO.getType().equals(thisKeyFieldType) || FieldTypeEnum.RADIO_GROUP.getType().equals(thisKeyFieldType)){
                            JSONObject itemJSON = thisData.getJSONObject(thisKey);
                            thisData.put(thisKey, itemJSON.get("text"));
                        } else if (FieldTypeEnum.USER_GROUP.getType().equals(thisKeyFieldType) || FieldTypeEnum.DEPT_GROUP.getType().equals(thisKeyFieldType)) {
                            JSONArray jsonArray = thisData.getJSONArray(thisKey);
                            JSONArray objects = new JSONArray();
                            for (int i = 0; i < jsonArray.size(); i++) {
                                JSONObject itemJSON = jsonArray.getJSONObject(i);
                                Object text = itemJSON.get("id");
                                objects.add(text);
                            }
                            thisData.put(thisKey, objects);
                        } else if (FieldTypeEnum.USER.getType().equals(thisKeyFieldType) || FieldTypeEnum.DEPT.getType().equals(thisKeyFieldType)) {
                            JSONObject itemJSON = thisData.getJSONObject(thisKey);
                            thisData.put(thisKey, itemJSON.get("id"));
                        }
                    }
                    for (int i = 0; i < productArray.size(); i++) {
                        JSONObject jsonObject = productArray.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(SelectProductEnum.PRODUCT.getAttr()), assembleProductData.getLongValue(SelectProductEnum.PRODUCT.getAttr()))) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }

        outStock.getData().put(OutstockEnum.PRODUCT.getAttr(),productArray);
        outStock.getData().put(OutstockEnum.TYPE.getAttr(),OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode());
        SaasFormSaveDTO outstockSaasFormSaveDTO = new SaasFormSaveDTO();
        BeanUtil.copyProperties(saasFormSaveDTO,outstockSaasFormSaveDTO);
        outstockSaasFormSaveDTO.setNewData(outStock.getData());
        outstockSaasFormSaveDTO.setNewPaasFormDataEntity(outStock);
        outstockSaasFormSaveDTO.setIsNew(true);
        outstockSaasFormSaveDTO.setBusinessType(XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
        outstockService.afterSave(outstockSaasFormSaveDTO);
    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put(ParameterConstant.ASSEMBLE_ID, pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE,  pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        if (Objects.equals(pagingProductDTO.getAttr(), AssembleEnum.OUT_PRODUCTS.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 1);
        } else if (Objects.equals(pagingProductDTO.getAttr(), AssembleEnum.IN_PRODUCTS.getAttr())) {
            modelMap.put(ParameterConstant.TYPE, 2);
        }
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, assembleProductModel, pagingProductDTO.getPageSize());
        List<AssembleProductEntity> assembleProductEntityList = (List<AssembleProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, assembleProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(assembleProductEntityList, pagingProductDTO);
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    public DetailProductVO formatProduct4DetailShow(List<AssembleProductEntity> assembleProductEntityList, PagingProductDTO pagingProductDTO) throws XbbException{
        DetailProductVO detailProductVO = new DetailProductVO();
        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<Long> assembleProductIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> warehouseIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> batchIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (AssembleProductEntity assembleProductEntity : assembleProductEntityList) {
            productIds.add(assembleProductEntity.getProductId());
            assembleProductIdSet.add(assembleProductEntity.getId());
            warehouseIdList.add(assembleProductEntity.getWarehouseId());
            warehouseKeySet.add(assembleProductEntity.getProductId() + "_" + assembleProductEntity.getWarehouseId());
        }
        List<PaasFormDataEntityExt> warehouseList = paasEsModel.getByIdList(warehouseIdList, pagingProductDTO.getCorpid(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WAREHOUSE.getCode(), new ArrayList<>(), IndexTypeEnum.IDX_SAAS_WAREHOUSE);
        Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : warehouseList) {
            JSONObject data = paasFormDataEntityExt.getData();
            warehouseNameMap.put(paasFormDataEntityExt.getId(), FastJsonHelper.getStringOrDefaultFromFormData(data, WarehouseEnum.WAREHOUSE_NAME.getAttr(), ""));
        }
        String corpid = pagingProductDTO.getCorpid();
        JSONArray productArray = new JSONArray();
        List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.getProductBaseInfoList(corpid, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode(), assembleProductIdSet);
        Map<Long, ProductBaseInfoEntity> baseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductBaseInfoEntity productBaseInfoEntity : productBaseInfoList) {
            baseInfoMap.put(productBaseInfoEntity.getRefId(), productBaseInfoEntity);
            if (StringUtil.isNotEmpty(productBaseInfoEntity.getBatch())) {
                batchIdList.add(productBaseInfoEntity.getBatch());
            }
        }
        Map<String, Double> productWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!warehouseKeySet.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
            params.put("warehouseKeyIn",warehouseKeySet);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params,null);
            productWarehouseEntities.forEach(item -> {
                String key = item.getProductId() + "_" + item.getWarehouseId();
                productWarehouseMap.put(key, item.getNum());
            });
        }
        if (!productIds.isEmpty() && !warehouseIdList.isEmpty() && !batchIdList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
            params.put("productIdIn", productIds);
            params.put("warehouseIdIn", warehouseIdList);
            params.put("batchIn", batchIdList);
            List<ProductStockEntity> productStockEntities = productStockModel.findEntitys(params);
            productStockEntities.forEach(item -> {
                productWarehouseMap.put(item.getBatchKey(), item.getNum());
            });
        }
        for (AssembleProductEntity assembleProductEntity : assembleProductEntityList) {
            ProductBaseInfoEntity productBaseInfoEntity = baseInfoMap.getOrDefault(assembleProductEntity.getId(), new ProductBaseInfoEntity());
            JSONObject json = new JSONObject();
            Double stock;
            if (StringUtil.isNotEmpty(productBaseInfoEntity.getBatch())) {
                stock = productWarehouseMap.getOrDefault(formDataValidateProductHelp.getBatchKey(assembleProductEntity.getProductId(), assembleProductEntity.getWarehouseId(), productBaseInfoEntity.getBatch(), productBaseInfoEntity.getProduceDate(), productBaseInfoEntity.getGuaranteePeriod()), 0D);
            } else {
                stock = productWarehouseMap.getOrDefault(assembleProductEntity.getProductId() + "_" + assembleProductEntity.getWarehouseId(), 0D);
            }
            if (Objects.nonNull(assembleProductEntity.getData())) {
                json = assembleProductEntity.getData();
            }
            if (Objects.nonNull(assembleProductEntity.getBusinessUnit())) {
                assembleProductEntity.setProductNum(Arith.div(assembleProductEntity.getProductNum(), assembleProductEntity.getRate()));
                assembleProductEntity.setProductUnit(assembleProductEntity.getBusinessUnit().toString());
                if (Objects.nonNull(assembleProductEntity.getPriceData())) {
                    assembleProductEntity.setCost(assembleProductEntity.getPriceData().getDouble(SelectProductEnum.COST.getAttr()));
                }
            }
            for (AssembleProductEnum assembleProductEnum : AssembleProductEnum.values()) {
                if (!UpdateDataTypeEnum.DETAIL.formatShow(assembleProductEnum.getShowType())) {
                    continue;
                }
                String attr = assembleProductEnum.getAttr();
                switch (assembleProductEnum) {
                    case PRODUCT:
                        json.put(attr, assembleProductEntity.getProductId());
                        break;
                    case WAREHOUSE:
                        JSONArray warehouseArr = productHelp.packegeLinkBusinessJsonArray(assembleProductEntity.getWarehouseId(),
                                warehouseNameMap.getOrDefault(assembleProductEntity.getWarehouseId(), ""), XbbRefTypeEnum.WAREHOUSE.getCode(), SaasMarkEnum.SAAS.getCode());
                        json.put(attr, warehouseArr);
                        break;
                    case STOCK:
                        json.put(attr, stock);
                        break;
                    case NUM:
                        json.put(attr, assembleProductEntity.getProductNum());
                        break;
                    case COST:
                        json.put(attr, assembleProductEntity.getCost());
                        break;
                    case TOTAL_COST:
                        if (Objects.nonNull(assembleProductEntity.getProductNum()) && Objects.nonNull(assembleProductEntity.getCost())) {
                            json.put(attr, Arith.mul(assembleProductEntity.getProductNum(), assembleProductEntity.getCost()));
                        }
                        break;
                    case MEMO:
                        json.put(attr, StringUtil.isNotEmpty(productBaseInfoEntity.getMemo()) ? productBaseInfoEntity.getMemo():assembleProductEntity.getMemo());
                        break;
                    case UNIT:
                        json.put(attr,  assembleProductEntity.getProductUnit());

                        break;
                    default:
                        break;
                }
            }
            if (Objects.equals(json.getDouble(SelectProductEnum.GUARANTEE_PERIOD.getAttr()), 0D)) {
                if (Objects.equals(json.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), 0L) || Objects.isNull(json.get(SelectProductEnum.PRODUCE_DATE.getAttr()))) {
                    json.remove(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
                }
            }
            json.put(BusinessConstant.PRODUCT_SUB_ID, assembleProductEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }

    @Override
    public void formatProduct4Show2(Long dataId, String corpid, JSONObject data, Boolean forProcess, Integer operate, UpdateDataTypeEnum updateDataTypeEnum) throws XbbException {
        assembleModel.formatProduct4Show2(dataId, corpid, data, forProcess, operate, updateDataTypeEnum);
    }

    @Override
    public JSONObject formatSingleProduct(AssembleProductEntity assembleProductEntity,ProductBaseInfoEntity productBaseInfoEntity) {
        return assembleModel.formatSingleProduct(assembleProductEntity, productBaseInfoEntity);
    }

    @Override
    public void dataConsistencyUpdateWarehouse(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0));
            BoolQueryBuilder filter1 = boolQuery()
                    .filter(termQuery("data." + AssembleEnum.INTO_WAREHOUSE_ID.getAttr() + ".keyword", dataId));
            BoolQueryBuilder filter2 = boolQuery()
                    .filter(termQuery("data." + AssembleEnum.OUT_WAREHOUSE_ID.getAttr() + ".keyword", dataId));
            filter.should(filter1);
            filter.should(filter2);
            filter.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_ASSEMBLE, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<AssembleEntityExt> assembleEntityExtList = assembleModel.findEntitys(param);
            if (Objects.nonNull(assembleEntityExtList) && !assembleEntityExtList.isEmpty()) {
                List<AssembleUpdateDTO> assembleUpdateDTOList = new ArrayList<>();
                for (AssembleEntityExt assembleEntityExt : assembleEntityExtList) {
                    JSONObject data = assembleEntityExt.getData();
                    Long inWarehouseId = data.getLong(AssembleEnum.INTO_WAREHOUSE_ID.getAttr());
                    Long outWarehousId = data.getLong(AssembleEnum.OUT_WAREHOUSE_ID.getAttr());
                    AssembleUpdateDTO assembleUpdateDTO = new AssembleUpdateDTO();
                    assembleUpdateDTO.setId(assembleEntityExt.getId());
                    JSONObject updateData = new JSONObject();
                    if (Objects.equals(inWarehouseId, dataId)) {
                        updateData.put(AssembleEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), name);
                    } else if (Objects.equals(outWarehousId, dataId)) {
                        updateData.put(AssembleEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), name);
                    }
                    assembleUpdateDTO.setData(updateData);

                    assembleUpdateDTOList.add(assembleUpdateDTO);
                }
                AssembleUpdateBatchDTO assembleUpdateBatchDTO = new AssembleUpdateBatchDTO();
                assembleUpdateBatchDTO.setCorpid(corpid);
                assembleUpdateBatchDTO.setAssembleList(assembleUpdateDTOList);
                updateBatch(assembleUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("AssembleServiceImpl.dataConsistencyUpdateWarehouse 出错， corpid=" + corpid + "  warehouseId=" + dataId + "  warehouseName=" + name, e);
        }
    }

    @Override
    public void updateBatchByBusinessRule(AssembleUpdateByBusinessRuleDTO assembleUpdateByBusinessRuleDTO) throws XbbException {
        try {
            String corpid = assembleUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = assembleUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(formDataList, corpid, assembleUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                assembleModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(assembleUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("productionOrderService.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void formatBatchExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        BatchSeqExplainHelp.getInstance().formatExplain4BatchAffectProductAttr(fieldAttrEntityList, enable, AssembleEnum.OUT_PRODUCTS.getAttr());
        BatchSeqExplainHelp.getInstance().formatExplain4BatchAffectProductAttr(fieldAttrEntityList, enable, AssembleEnum.IN_PRODUCTS.getAttr());
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        AssembleUpdateBatchDTO assembleUpdateBatchDTO = new AssembleUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, assembleUpdateBatchDTO);
        List<AssembleUpdateDTO> assembleUpdate = new ArrayList<>();
        addBatchList.forEach(item->{
            AssembleUpdateDTO updateDTO= new AssembleUpdateDTO();
            updateDTO.setData(item.getData());
            updateDTO.setId(item.getId());
            assembleUpdate.add(updateDTO);
        });
        assembleUpdateBatchDTO.setAssembleList(assembleUpdate);
        updateBatch(assembleUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) {
        if (saasFormSaveDTO.getIsNew()) {
            try {
                saveProduct(saasFormSaveDTO.getNewData(), saasFormSaveDTO.getCorpid(), saasFormSaveDTO.getNewPaasFormDataEntity().getId());
//                    generateStockSheet(saasFormSaveDTO);
//                    saasSaveHelp.generateStockSheet(saasFormSaveDTO);
            } catch (Exception e) {
                LOG.error("AssembleServiceImpl.afterSaveForWorkflow 执行出错", e);
            }
        }
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException{
        String corpid = saasFormSaveDTO.getCorpid();
        Long dataId = saasFormSaveDTO.getNewPaasFormDataEntity().getId();
        PaasFormDataEntity paasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject data = paasFormDataEntity.getData();
        JSONArray outProductArray = data.getJSONArray(AssembleEnum.OUT_PRODUCTS.getAttr());
        JSONArray inProductArray = data.getJSONArray(AssembleEnum.IN_PRODUCTS.getAttr());
        // 出库
        saveAssembleProduct(corpid, outProductArray, dataId, 1);
        // 入库
        saveAssembleProduct(corpid, inProductArray, dataId, 2);
    }

    /**
     * 工作流保存产品
     * @param corpid
     * @param productArray
     * @param dataId
     * @param type 1装配出库产品 2装配入库产品
     * @throws XbbException
     */
    private void saveAssembleProduct(String corpid, JSONArray productArray, Long dataId, Integer type) throws XbbException {
        //非新建情况下，取得盘点单编辑前的关联产品
        Map<Long, AssembleProductEntity> orginProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, ProductBaseInfoEntity> orginProductBaseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<AssembleProductEntity> assembleProductList = assembleProductModel.getProductsByAssembleId(dataId,corpid, type, Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
        List<Long> refProductIdList = new ArrayList<>(assembleProductList.size());
        for (AssembleProductEntity assembleProductEntity : assembleProductList) {
            orginProductMap.put(assembleProductEntity.getId(), assembleProductEntity);
            refProductIdList.add(assembleProductEntity.getId());
        }
        if (!refProductIdList.isEmpty()) {
            List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.getProductBaseInfoList(corpid, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode(), refProductIdList);
            productBaseInfoList.forEach(item -> orginProductBaseInfoMap.put(item.getRefId(), item));
        }
        long now = DateTimeUtil.getInt();
        List<AssembleProductEntity> productUpdateList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<AssembleProductEntity> productInsertList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Integer, AssembleProductEntity> productInsertMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        List<ProductBaseInfoEntity> addProductBaseInfoList = new ArrayList<>();
        Map<Integer, ProductBaseInfoEntity> addProductBaseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ProductBaseInfoEntity> updateProductBaseInfoList = new ArrayList<>();
        Map<Integer, JSONObject> inProductSeqMap = new HashMap<>(productArray.size());
        Integer sort = 0;
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            JSONArray seqArray = jsonObject.getJSONArray(ProductConstant.SEQ);
            // 去除序列号数据, 序列号数据不保存在关联产品表中
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Double productNum = jsonObject.getDouble(AssembleProductEnum.NUM.getAttr());
            String memo = jsonObject.getString(AssembleInProductEnum.MEMO.getAttr());
            JSONObject productData = productMap.get(pageProductId).getData();
            AssembleProductEntity assembleProduct;
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            if (addProductFlag) {
                //新增产品
                assembleProduct = new AssembleProductEntity();
            } else if (orginProductMap.containsKey(businessProductId)) {
                //编辑产品
                assembleProduct = orginProductMap.get(businessProductId);
                assembleProduct.setUpdateTime(now);
                productUpdateList.add(assembleProduct);
                //只剩删除的产品
                orginProductMap.remove(businessProductId);
            } else {
                //删除产品
                continue;
            }
            assembleProduct.setCorpid(corpid);
            assembleProduct.setAssembleId(dataId);
            assembleProduct.setType(type);
            assembleProduct.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            assembleProduct.setProductId(pageProductId);
            assembleProduct.setProductNum(productNum);
            assembleProduct.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            assembleProduct.setProductNo(productMap.get(pageProductId).getSerialNo());
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, assembleProduct);
                assembleProduct.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                assembleProduct.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(TransferProductEnum.UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            assembleProduct.setCost(jsonObject.getDouble(AssembleProductEnum.COST.getAttr()));
            assembleProduct.setProductPrice(productData.getDouble(ProductEnum.PRICE.getAttr()));
            assembleProduct.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            saasSaveHelp.formatLinkBusiness4Save(jsonObject,AssembleProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            Long warehouseId = jsonObject.getLong(AssembleProductEnum.WAREHOUSE.getAttr());
            assembleProduct.setWarehouseId(warehouseId);
            Double productPrice = jsonObject.getDouble(ProductEnum.PRICE.getAttr());
            assembleProduct.setProductPrice(null == productPrice ? 0L : productPrice);
            assembleProduct.setAddTime(DateTimeUtil.getInt());
            assembleProduct.setUpdateTime(DateTimeUtil.getInt());
            assembleProduct.setDel(0);
            sort++;
            assembleProduct.setSort(sort);
            assembleProduct.setMemo(memo);
            assembleProduct.setBatch(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()));
            assembleProduct.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
            Long guaranteePeriod = jsonObject.getLong(AssembleProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : jsonObject.getLong(AssembleProductEnum.GUARANTEE_PERIOD.getAttr());
            assembleProduct.setGuaranteePeriod(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
            assembleProduct.setData(jsonObject);
            if (addProductFlag) {
                // 就离谱，非要在这里insert，因为jsonObject还会往下传，离谱
//                assembleProductModel.insert(assembleProduct);
                productInsertList.add(assembleProduct);
                productInsertMap.put(i, assembleProduct);
            }

//            jsonObject.put(BusinessConstant.REF_PRODUCT_ID, assembleProduct.getId());
            if (Objects.nonNull(seqArray) && !seqArray.isEmpty()) {
                JSONObject seqJson = new JSONObject();
                seqJson.put(ProductConstant.SEQ, seqArray);
                seqJson.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), jsonObject.getIntValue(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr()));
                inProductSeqMap.put(i, seqJson);
            }
            if (StringUtil.isNotEmpty(jsonObject.getString(AssembleProductEnum.BATCH.getAttr())) && !orginProductBaseInfoMap.containsKey(assembleProduct.getId())) {
                JSONObject productBaseInfoData = new JSONObject();
                productBaseInfoData.putAll(jsonObject);
                if (Objects.nonNull(assembleProduct.getBusinessUnit())) {
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_UNIT.getAttr(), assembleProduct.getBusinessUnit());
                    productBaseInfoData.put(SelectProductEnum.RATE.getAttr(), assembleProduct.getRate());
                    productBaseInfoData.put(SelectProductEnum.UNIT_GROUP.getAttr(), assembleProduct.getGroupId());
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_NUM.getAttr(), assembleProduct.getBusinessNum());
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_COST.getAttr(),assembleProduct.getPriceData().get(SelectProductEnum.COST.getAttr()));
                }
                ProductBaseInfoEntity productBaseInfoEntity = new ProductBaseInfoEntity();
                productBaseInfoEntity.setCorpid(corpid);
                productBaseInfoEntity.setFormId(0L);
                productBaseInfoEntity.setRefId(assembleProduct.getId());
                productBaseInfoEntity.setRefType(XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
                productBaseInfoEntity.setBatch(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()));
                productBaseInfoEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
                productBaseInfoEntity.setGuaranteePeriod(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                productBaseInfoEntity.setMemo(jsonObject.getString(AssembleProductEnum.MEMO.getAttr()));
                productBaseInfoEntity.setData(productBaseInfoData);
                productBaseInfoEntity.setDel(0);
                productBaseInfoEntity.setAddTime(DateTimeUtil.getInt());
                productBaseInfoEntity.setUpdateTime(DateTimeUtil.getInt());
                addProductBaseInfoMap.put(i, productBaseInfoEntity);
//                addProductBaseInfoList.add(productBaseInfoEntity);
            } else if (!addProductFlag && orginProductBaseInfoMap.containsKey(assembleProduct.getId())){
                ProductBaseInfoEntity productBaseInfoEntity = orginProductBaseInfoMap.get(assembleProduct.getId());
                productBaseInfoEntity.setBatch(jsonObject.getString(AssembleProductEnum.BATCH.getAttr()));
                productBaseInfoEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
                productBaseInfoEntity.setGuaranteePeriod(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                productBaseInfoEntity.setMemo(jsonObject.getString(AssembleProductEnum.MEMO.getAttr()));
                productBaseInfoEntity.setData(jsonObject);
                productBaseInfoEntity.setUpdateTime(now);
                updateProductBaseInfoList.add(productBaseInfoEntity);
                orginProductBaseInfoMap.remove(assembleProduct.getId());
            }
        }

        if (!productUpdateList.isEmpty()) {
            assembleProductModel.updateBatch(productUpdateList, corpid);
        }
        if (!productInsertList.isEmpty()) {
            assembleProductModel.insertBatch(productInsertList);
        }
        productInsertMap.forEach((i, value)->{
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long id = value.getId();
            jsonObject.put(BusinessConstant.REF_PRODUCT_ID, id);
            if (inProductSeqMap.containsKey(i)) {
                jsonObject.putAll(inProductSeqMap.get(i));
            }
            if (addProductBaseInfoMap.containsKey(i)) {
                ProductBaseInfoEntity productBaseInfoEntity = addProductBaseInfoMap.get(i);
                productBaseInfoEntity.setRefId(id);
                productBaseInfoEntity.getData().put(BusinessConstant.REF_PRODUCT_ID, id);
                addProductBaseInfoMap.put(i, productBaseInfoEntity);
            }
        });
        addProductBaseInfoMap.forEach((key, value)->{
            addProductBaseInfoList.add(value);
        });
        if (!addProductBaseInfoList.isEmpty()){
            productBaseInfoModel.insertBatch(addProductBaseInfoList);
        }
        if (!updateProductBaseInfoList.isEmpty()){
            //
            productBaseInfoModel.updateBatch(updateProductBaseInfoList, corpid);
        }

        List<Long> delRefIdList = new ArrayList<>();
        for (Map.Entry<Long, AssembleProductEntity> entry : orginProductMap.entrySet()) {
            AssembleProductEntity delProduct = entry.getValue();
            delRefIdList.add(delProduct.getId());
        }
        if (!delRefIdList.isEmpty()){
            assembleProductModel.deleteBatch(delRefIdList, corpid, DelEnum.DELETE.getDel());
            productBaseInfoModel.deleteByRefIds(corpid,delRefIdList,XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
        }
    }

    @Override
    public void formatBatchOrSeqExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable, String alias) {
        if (Objects.equals(CompanyConfigEnum.ENABLE_BATCH_SHELF_MANAGEMENT.getAlias(), alias)) {
            formatBatchExplain(fieldAttrEntityList, enable);
        }
    }
}
